#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
智能化漏洞检测与攻击路径分析平台 - Git推送辅助脚本

此脚本用于帮助用户初始化Git仓库并推送到Gitee，简化推送流程。
"""

import os
import sys
import subprocess
import json
import time
from datetime import datetime

# 项目根目录
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

# 日志文件路径
LOG_FILE = os.path.join(PROJECT_ROOT, "git_push_log.txt")

# 默认配置
DEFAULT_REPO_NAME = "vulnerability-scanner"
DEFAULT_REPO_DESC = "智能化漏洞检测与攻击路径分析平台"


def log(message, level="INFO"):
    """记录日志消息到控制台和文件"""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_message = f"[{timestamp}] [{level}] {message}"
    
    # 输出到控制台
    if level == "ERROR":
        print("\033[91m" + log_message + "\033[0m")  # 红色
    elif level == "WARNING":
        print("\033[93m" + log_message + "\033[0m")  # 黄色
    elif level == "SUCCESS":
        print("\033[92m" + log_message + "\033[0m")  # 绿色
    else:
        print(log_message)  # 白色
    
    # 写入日志文件
    with open(LOG_FILE, "a", encoding="utf-8") as f:
        f.write(log_message + "\n")


def run_command(command, cwd=None, shell=True, check=True):
    """运行命令并返回结果"""
    if cwd is None:
        cwd = PROJECT_ROOT
    
    log(f"执行命令: {command}")
    try:
        result = subprocess.run(
            command,
            cwd=cwd,
            shell=shell,
            check=check,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        if result.stdout.strip():
            log(f"命令输出: {result.stdout.strip()}")
        return result
    except subprocess.CalledProcessError as e:
        log(f"命令执行失败: {e}", "ERROR")
        if e.stdout.strip():
            log(f"标准输出: {e.stdout.strip()}", "ERROR")
        if e.stderr.strip():
            log(f"错误输出: {e.stderr.strip()}", "ERROR")
        raise


def check_git_installed():
    """检查Git是否已安装"""
    log("检查Git是否已安装...")
    try:
        result = run_command("git --version", check=True)
        log(f"Git版本: {result.stdout.strip()}", "SUCCESS")
        return True
    except Exception as e:
        log("错误: Git未安装或不在PATH中。请先安装Git。", "ERROR")
        log("Git下载地址: https://git-scm.com/downloads", "INFO")
        return False


def check_git_config():
    """检查Git配置"""
    log("检查Git用户配置...")
    try:
        # 检查用户名
        username = run_command("git config user.name", check=False).stdout.strip()
        # 检查邮箱
        email = run_command("git config user.email", check=False).stdout.strip()
        
        if not username or not email:
            log("警告: Git用户配置不完整", "WARNING")
            log(f"当前配置 - 用户名: {'已设置' if username else '未设置'}", "INFO")
            log(f"当前配置 - 邮箱: {'已设置' if email else '未设置'}", "INFO")
            return False
        else:
            log(f"Git用户配置正确 - 用户名: {username}, 邮箱: {email}", "SUCCESS")
            return True
    except Exception as e:
        log(f"检查Git配置时出错: {e}", "ERROR")
        return False


def configure_git():
    """配置Git用户信息"""
    log("开始配置Git用户信息...")
    
    # 获取当前配置
    try:
        current_username = run_command("git config user.name", check=False).stdout.strip()
        current_email = run_command("git config user.email", check=False).stdout.strip()
    except:
        current_username = ""
        current_email = ""
    
    # 提示用户输入
    print(f"\n请输入您的Gitee用户名 (当前: {current_username if current_username else '未设置'}):")
    username = input().strip()
    if not username and not current_username:
        log("错误: 用户名不能为空", "ERROR")
        return False
    elif username:
        # 保存新用户名
        try:
            run_command('git config user.name "' + username + '"')
        except Exception as e:
            log(f"设置用户名失败: {e}", "ERROR")
            return False
    
    print(f"\n请输入您的邮箱地址 (当前: {current_email if current_email else '未设置'}):")
    email = input().strip()
    if not email and not current_email:
        log("错误: 邮箱不能为空", "ERROR")
        return False
    elif email:
        # 保存新邮箱
        try:
            run_command('git config user.email "' + email + '"')
        except Exception as e:
            log(f"设置邮箱失败: {e}", "ERROR")
            return False
    
    log("Git用户配置完成", "SUCCESS")
    return True


def check_gitignore():
    """检查.gitignore文件"""
    gitignore_path = os.path.join(PROJECT_ROOT, ".gitignore")
    if os.path.exists(gitignore_path):
        log(".gitignore文件已存在", "SUCCESS")
        return True
    else:
        log("警告: .gitignore文件不存在", "WARNING")
        return False


def init_git_repo():
    """初始化Git仓库"""
    log("初始化Git仓库...")
    
    # 检查.git目录是否存在
    git_dir = os.path.join(PROJECT_ROOT, ".git")
    if os.path.exists(git_dir) and os.path.isdir(git_dir):
        log("Git仓库已初始化", "WARNING")
        print("\n检测到仓库已初始化，是否重新初始化？(y/N):")
        choice = input().strip().lower()
        if choice != 'y':
            return True
    
    try:
        # 删除旧的.git目录（如果选择重新初始化）
        if os.path.exists(git_dir):
            import shutil
            shutil.rmtree(git_dir)
            log("已删除旧的Git仓库", "INFO")
        
        # 初始化新仓库
        run_command("git init")
        log("Git仓库初始化成功", "SUCCESS")
        return True
    except Exception as e:
        log(f"初始化Git仓库失败: {e}", "ERROR")
        return False


def add_and_commit():
    """添加文件并提交"""
    log("添加文件到暂存区...")
    try:
        # 添加所有文件
        run_command("git add .")
        log("文件添加成功", "INFO")
        
        # 检查是否有更改需要提交
        status_result = run_command("git status --porcelain", check=False)
        if not status_result.stdout.strip():
            log("没有文件需要提交", "WARNING")
            return True
        
        # 提交更改
        commit_message = f"初始化智能化漏洞检测与攻击路径分析平台项目 - {datetime.now().strftime('%Y-%m-%d')}"
        run_command('git commit -m "' + commit_message + '"')
        log("提交成功", "SUCCESS")
        return True
    except Exception as e:
        log(f"添加或提交文件失败: {e}", "ERROR")
        return False


def add_remote_repo():
    """添加远程仓库"""
    log("配置远程仓库...")
    
    # 检查是否已有远程仓库
    try:
        remote_result = run_command("git remote -v", check=False)
        if remote_result.stdout.strip():
            log("检测到已配置的远程仓库:", "WARNING")
            log(remote_result.stdout.strip(), "INFO")
            print("\n是否重新配置远程仓库？(y/N):")
            choice = input().strip().lower()
            if choice != 'y':
                return True
    except:
        pass
    
    # 获取用户的Gitee用户名
    print("\n请输入您的Gitee用户名:")
    gitee_username = input().strip()
    if not gitee_username:
        log("错误: Gitee用户名不能为空", "ERROR")
        return False
    
    # 获取仓库名称
    print(f"\n请输入仓库名称 (默认: {DEFAULT_REPO_NAME}):")
    repo_name = input().strip() or DEFAULT_REPO_NAME
    
    # 询问是否使用SSH或HTTPS
    print("\n请选择连接方式:")
    print("1. SSH (推荐，需要配置SSH密钥)")
    print("2. HTTPS (简单但每次推送需要输入密码)")
    connection_type = input("请选择 (1/2): ").strip()
    
    if connection_type == '1':
        # SSH URL
        remote_url = f"git@gitee.com:{gitee_username}/{repo_name}.git"
        log("使用SSH连接方式", "INFO")
        log("请确保已将SSH公钥添加到Gitee账户", "WARNING")
        log("生成SSH密钥命令: ssh-keygen -t ed25519 -C \"您的邮箱地址\"")
    else:
        # HTTPS URL
        remote_url = f"https://gitee.com/{gitee_username}/{repo_name}.git"
        log("使用HTTPS连接方式", "INFO")
    
    # 添加远程仓库
    try:
        # 先删除现有的remote origin（如果有）
        run_command("git remote remove origin", check=False)
        # 添加新的remote origin
        run_command(f"git remote add origin {remote_url}")
        log(f"远程仓库配置成功: {remote_url}", "SUCCESS")
        return True
    except Exception as e:
        log(f"配置远程仓库失败: {e}", "ERROR")
        return False


def push_to_gitee():
    """推送到Gitee"""
    log("推送到Gitee仓库...")
    
    try:
        # 推送到master分支
        log("正在推送代码，请稍候...")
        # 使用非阻塞方式执行，以便能够显示进度
        process = subprocess.Popen(
            "git push -u origin master",
            cwd=PROJECT_ROOT,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        
        # 实时显示输出
        while process.poll() is None:
            # 尝试读取输出
            stdout = process.stdout.readline()
            stderr = process.stderr.readline()
            if stdout:
                print(stdout.strip())
            if stderr:
                print("\033[93m" + stderr.strip() + "\033[0m")
            time.sleep(0.1)
        
        # 检查退出码
        if process.returncode == 0:
            log("推送成功！代码已上传到Gitee仓库", "SUCCESS")
            log("您可以在浏览器中访问仓库页面查看", "INFO")
            return True
        else:
            # 读取剩余输出
            stdout, stderr = process.communicate()
            if stdout:
                log(stdout.strip(), "ERROR")
            if stderr:
                log(stderr.strip(), "ERROR")
            
            log(f"推送失败，退出码: {process.returncode}", "ERROR")
            log("可能的解决方案:", "INFO")
            log("1. 确保您的Gitee仓库已创建", "INFO")
            log("2. 检查您的SSH密钥是否已正确配置", "INFO")
            log("3. 如果远程仓库已有内容，可能需要先拉取: git pull origin master --allow-unrelated-histories", "INFO")
            
            # 询问是否尝试拉取
            print("\n是否尝试拉取远程仓库内容并再次推送？(y/N):")
            choice = input().strip().lower()
            if choice == 'y':
                try:
                    run_command("git pull origin master --allow-unrelated-histories")
                    # 再次推送
                    return push_to_gitee()
                except Exception as e:
                    log(f"拉取失败: {e}", "ERROR")
                    return False
            return False
    except Exception as e:
        log(f"推送过程中发生错误: {e}", "ERROR")
        return False


def verify_push():
    """验证推送结果"""
    log("验证推送结果...")
    try:
        # 检查远程分支信息
        result = run_command("git ls-remote --heads origin", check=False)
        if result.returncode == 0 and "refs/heads/master" in result.stdout:
            log("推送验证成功！master分支已存在于远程仓库", "SUCCESS")
            # 尝试获取远程仓库URL
            remote_url = run_command("git config --get remote.origin.url", check=False).stdout.strip()
            if remote_url:
                # 将git@或https:// URL转换为浏览器URL
                if remote_url.startswith("git@gitee.com:"):
                    web_url = remote_url.replace("git@gitee.com:", "https://gitee.com/")
                else:
                    web_url = remote_url
                log(f"您可以通过以下链接访问仓库: {web_url}", "SUCCESS")
        else:
            log("警告: 无法验证远程master分支", "WARNING")
    except Exception as e:
        log(f"验证过程中发生错误: {e}", "WARNING")


def show_gitee_guide():
    """显示Gitee操作指南"""
    print("\n" + "="*60)
    print("          Gitee仓库创建指南")
    print("="*60)
    print("1. 登录您的Gitee账号 (https://gitee.com)")
    print("2. 点击右上角「+」按钮，选择「新建仓库」")
    print("3. 填写仓库信息:")
    print(f"   - 仓库名称: {DEFAULT_REPO_NAME}")
    print(f"   - 路径: 建议与名称相同")
    print(f"   - 仓库介绍: {DEFAULT_REPO_DESC}")
    print("   - 选择公开/私有: 根据需求选择")
    print("   - 初始化仓库: 不要勾选")
    print("   - 分支模型: 默认即可")
    print("4. 点击「创建仓库」按钮")
    print("="*60 + "\n")
    
    # 等待用户确认
    input("请在Gitee上创建仓库后按Enter键继续...")


def main():
    """主函数"""
    # 清空旧日志
    open(LOG_FILE, "w").close()
    log("开始Git推送辅助脚本")
    
    print("\n" + "="*60)
    print("    智能化漏洞检测与攻击路径分析平台 - Git推送助手")
    print("="*60)
    
    # 1. 显示Gitee创建指南
    show_gitee_guide()
    
    # 2. 检查Git是否安装
    if not check_git_installed():
        return 1
    
    # 3. 检查并配置Git用户信息
    if not check_git_config():
        print("\n需要配置Git用户信息")
        if not configure_git():
            return 1
    
    # 4. 检查.gitignore文件
    check_gitignore()
    
    # 5. 初始化Git仓库
    if not init_git_repo():
        return 1
    
    # 6. 添加并提交文件
    if not add_and_commit():
        return 1
    
    # 7. 添加远程仓库
    if not add_remote_repo():
        return 1
    
    # 8. 推送到Gitee
    if not push_to_gitee():
        log("推送失败，请参考日志解决问题", "ERROR")
        log(f"详细日志: {LOG_FILE}")
        return 1
    
    # 9. 验证推送结果
    verify_push()
    
    log("\nGit推送流程完成！", "SUCCESS")
    log("您的项目代码已成功推送到Gitee仓库", "SUCCESS")
    log("接下来，您可以使用check_and_run.py脚本启动和测试系统")
    
    print("\n" + "="*60)
    print("          推送完成")
    print("="*60)
    print("提示: 如需运行系统，请使用以下命令:")
    print("python check_and_run.py --force")
    print("="*60)
    
    return 0


if __name__ == "__main__":
    exit_code = main()
    input("\n按Enter键退出...")  # 防止脚本立即关闭
    sys.exit(exit_code)